﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LightCAD.MathLib.CSG.Mesh;
using System.Windows.Forms.VisualStyles;

namespace LightCAD.MathLib.CSG
{
   class EdgeEntry
    {
        public int vid;
        // things
        public TopoEdge e;

        public EdgeEntry(int id)
        {
            this.vid = id;
        }
        EdgeEntry() { }
    };
   class EdgeCache
    {
        IsctProblem iprob;
        List<List<EdgeEntry>> edges = new List<List<EdgeEntry>>();
        public EdgeCache(IsctProblem ip)
        {
            this.iprob = ip;
            edges.resize(ip.mesh.verts.size(),()=>new List<EdgeEntry>());
        }

        public TopoEdge getEdge(TopoVert v0, TopoVert v1)
        {
            int i = v0.@ref;
            int j = v1.@ref;
            if (i > j) Utils.swap(ref i, ref j);

            int N = edges[i].size();
            for (int k = 0; k < N; k++)
                if (edges[i][k].vid == j)
                    return edges[i][k].e;
            // if not existing, create it
            edges[i].push_back(new EdgeEntry(j));
            var e = edges[i][N].e = iprob.newEdge().datum;
            e.verts[0] = v0;
            e.verts[1] = v1;
            v0.edges.push_back(e);
            v1.edges.push_back(e);

            return e;
        }

        // k = 0, 1, or 2
        public TopoEdge getTriangleEdge(GenericTriType gt, int k, TopoTri big_tri)
        {
            var gv0 = gt.verts[(k + 1) % 3];
            var gv1 = gt.verts[(k + 2) % 3];
            var v0 = gv0.concrete;
            var v1 = gv1.concrete;
            // if neither of these are intersection points,
            // then this is a pre-existing edge...
            TopoEdge e = null;
            if (gv0  is OrigVertType && gv1  is OrigVertType  )
            {
                // search through edges of original triangle...
                for (int c = 0; c < 3; c++)
                {
                    var corner0 = big_tri.verts[(c + 1) % 3];
                    var corner1 = big_tri.verts[(c + 2) % 3];
                    if ((corner0 == v0 && corner1 == v1) ||
                       (corner0 == v1 && corner1 == v0))
                    {
                        e = big_tri.edges[c];
                    }
                }
                Utils.ENSURE(e!=null); // Yell if we didn't find an edge
            }
            // otherwise, we need to check the cache to find this edge
            else
            {
                e = getEdge(v0, v1);
            }
            return e;
        }

        public TopoEdge maybeEdge(GenericEdgeType ge)
        {
            int i = ge.ends[0].concrete.@ref;
            int j = ge.ends[1].concrete.@ref;
            if (i > j) Utils.swap(ref i, ref j);

            int N = edges[i].size();
            for (int k = 0; k < N; k++)
                if (edges[i][k].vid == j)
                    return edges[i][k].e;
            // if we can't find it
            return null;
        }

    };
}
